
# 分词器
import jieba
# 自然语言处理包
from pyhanlp import HanLP
# from snownlp import SnowNLP


# 1.实体抽取

# 示例文本
text = "齿轮是机械传动中常用的部件，热处理是提高其性能的重要技术。"

# 分词
words = jieba.lcut(text)
print("分词结果:", words)

# 命名实体识别
ner_result = HanLP.newSegment().enableOrganizationRecognize(True).enablePlaceRecognize(True).enableNameRecognize(True).seg(text)
for term in ner_result:
    if term.nature.startsWith('n'):  # 假设以 'n' 开头的词性为名词实体
        print("识别到的实体:", term.word, "词性:", term.nature)

# 使用 SnowNLP 进行词性标注
# s = SnowNLP(text)
# tags = s.tags

# 过滤出以 'n' 开头词性的名词实体
# print("识别到的实体:")
# for word, tag in tags:
#     # print(word,tag)
#     if tag.startswith('n'):
#         print(f"实体: {word}, 词性: {tag}")

# for i in words:
#     s = SnowNLP(i)
#     tags = s.tags
#     for word,tag in tags:
#         if tag.startswith('n'):
#             print(word,tag)

# 2.关系抽取

# 示例文本
text = "发动机是汽车的重要组成部分。"

# 定义关系关键词
relation_keywords = {
    "组成关系": ["是……的组成部分", "组成"]
}

# 遍历关系关键词
for relation, keywords in relation_keywords.items():
    for keyword in keywords:
        if keyword in text:
            # 提取实体
            parts = text.split(keyword)
            entity1 = parts[0].strip()
            entity2 = parts[1].strip()
            print(f"识别到的关系: {entity1} - {relation} - {entity2}")

# 3.属性抽取
# 示例文本
text = "这个齿轮的模数是 2，齿数为 30。"

# 定义属性关键词
attribute_keywords = {
    "模数": ["模数是"],
    "齿数": ["齿数为"]
}

# 遍历属性关键词
for attribute, keywords in attribute_keywords.items():
    for keyword in keywords:
        if keyword in text:
            start_index = text.find(keyword) + len(keyword)
            end_index = text.find("，", start_index)
            if end_index == -1:
                end_index = len(text)
            value = text[start_index:end_index].strip()
            print(f"识别到的属性: 齿轮 - {attribute} - {value}")

# 4.知识图谱构建
'''
from py2neo import Graph, Node, Relationship

# 连接到 Neo4j 数据库
# 这里需要根据你的 Neo4j 数据库设置修改地址、用户名和密码
graph = Graph("neo4j+s://7df5578a.databases.neo4j.io", auth=("neo4j", "12345678"))

# 定义实体、关系和属性信息
# 实体
entity1 = "齿轮"
entity2 = "机械传动"
entity3 = "热处理"
entity4 = "汽车"
entity5 = "发动机"

# 关系
relations = [
    (entity1, "应用于", entity2),
    (entity1, "处理方式", entity3),
    (entity5, "组成关系", entity4)
]

# 属性
attributes = [
    (entity1, "模数", "2"),
    (entity1, "齿数", "30")
]

# 创建节点
nodes = {}
for entity in [entity1, entity2, entity3, entity4, entity5]:
    node = Node("机械实体", name=entity)
    nodes[entity] = node
    graph.create(node)

# 创建关系
for source_entity, relation_type, target_entity in relations:
    source_node = nodes[source_entity]
    target_node = nodes[target_entity]
    rel = Relationship(source_node, relation_type, target_node)
    graph.create(rel)

# 添加属性
for entity, attribute_name, attribute_value in attributes:
    node = nodes[entity]
    node[attribute_name] = attribute_value
    graph.push(node)

print("知识图谱构建完成！")
'''
# 5.知识问答系统设计
from py2neo import Graph
# 连接到 Neo4j 数据库
graph = Graph("neo4j+s://7df5578a.databases.neo4j.io", auth=("neo4j", "12345678"))

# 问题理解：简单的分词和关键词提取
def understand_question(question):
    words = jieba.lcut(question)
    entities = []
    for word in words:
        # 这里简单假设名词为实体，实际应用可使用更复杂的实体识别方法
        if len(word) > 1:
            entities.append(word)
    return entities

# 知识图谱查询
def query_knowledge_graph(entities):
    if len(entities) == 1:
        # 查询与该实体相关的所有关系和其他实体
        cypher_query = f"MATCH (e1:机械实体 {{name: '{entities[0]}'}})-[r]->(e2:机械实体) RETURN type(r) as relation, e2.name as target_entity"
    elif len(entities) == 2:
        # 查询两个实体之间的关系
        cypher_query = f"MATCH (e1:机械实体 {{name: '{entities[0]}'}})-[r]->(e2:机械实体 {{name: '{entities[1]}'}}) RETURN type(r) as relation"
    else:
        return []
    results = graph.run(cypher_query).data()
    return results

# 答案生成
def generate_answer(question, results):
    if not results:
        return "抱歉，未找到相关答案。"
    if len(results[0]) == 1:
        relation = results[0]['relation']
        answer = f"{question}，它们之间的关系是：{relation}。"
    else:
        answer = f"{question} 的相关信息如下："
        for result in results:
            relation = result['relation']
            target_entity = result['target_entity']
            answer += f"\n - 与 {target_entity} 存在 {relation} 关系。"
    return answer

# 主问答函数
def answer_question(question):
    entities = understand_question(question)
    results = query_knowledge_graph(entities)
    answer = generate_answer(question, results)
    return answer

# 示例使用
question = "齿轮与机械传动有什么关系"
answer = answer_question(question)
print(answer,'v1')

# 问题理解：使用HanLP进行命名实体识别
def understand_question(question):
    # 这里使用HanLP进行命名实体识别，假设以 'n' 开头的词性为名词实体
    ner_result = HanLP.newSegment().enableNameRecognize(True).seg(question)
    entities = [term.word for term in ner_result if term.nature.startsWith('n')]
    return entities

# 知识图谱查询
def query_knowledge_graph(entities):
    if len(entities) == 1:
        # 查询与该实体相关的所有关系和其他实体
        cypher_query = f"MATCH (e1:机械实体 {{name: '{entities[0]}'}})-[r]->(e2:机械实体) RETURN type(r) as relation, e2.name as target_entity"
    elif len(entities) == 2:
        # 查询两个实体之间的关系
        cypher_query = f"MATCH (e1:机械实体 {{name: '{entities[0]}'}})-[r]->(e2:机械实体 {{name: '{entities[1]}'}}) RETURN type(r) as relation"
    else:
        return []
    results = graph.run(cypher_query).data()
    return results

# 答案生成
def generate_answer(question, results):
    if not results:
        return "抱歉，未找到相关答案。"
    if len(results[0]) == 1:
        relation = results[0]['relation']
        answer = f"{question}，它们之间的关系是：{relation}。"
    else:
        answer = f"{question} 的相关信息如下："
        for result in results:
            relation = result['relation']
            target_entity = result['target_entity']
            answer += f"\n - 与 {target_entity} 存在 {relation} 关系。"
    return answer

# 主问答函数
def answer_question(question):
    entities = understand_question(question)
    results = query_knowledge_graph(entities)
    answer = generate_answer(question, results)
    return answer

# 示例使用
question = "齿轮与机械传动有什么关系"
answer = answer_question(question)
print(answer)

# 6.系统评估与优化
import numpy as np

# 模拟问答系统的回答结果和真实答案
# 假设我们有一组测试问题，以下是系统回答和真实答案的列表
system_answers = [
    "齿轮与机械传动存在应用于关系。",
    "发动机与汽车存在组成关系。",
    "抱歉，未找到相关答案。"
]
true_answers = [
    "齿轮与机械传动存在应用于关系。",
    "发动机是汽车的组成部分。",
    "该问题无有效答案。"
]

# 评估指标计算
def evaluate(system_answers, true_answers):
    correct_count = 0
    total_count = len(system_answers)

    for sys_ans, true_ans in zip(system_answers, true_answers):
        if sys_ans == true_ans:
            correct_count += 1

    # 计算准确率
    accuracy = correct_count / total_count

    return accuracy

# 优化策略模拟：简单的知识图谱补全
def optimize(knowledge_graph, low_accuracy):
    if low_accuracy:
        # 这里简单模拟添加一条新的知识到知识图谱
        new_relationship = "新的关系信息"
        knowledge_graph.append(new_relationship)
        print("已对知识图谱进行补全，添加了新的关系信息。")
    return knowledge_graph

# 进行评估
accuracy = evaluate(system_answers, true_answers)
print(f"问答系统的准确率为: {accuracy * 100:.2f}%")

# 判断是否需要优化
if accuracy < 0.8:  # 假设准确率低于 80% 时进行优化
    # 模拟知识图谱，这里用列表表示
    knowledge_graph = []
    updated_knowledge_graph = optimize(knowledge_graph, True)
else:
    print("问答系统准确率较高，暂不需要优化。")